/*
 *  doctorOffice.c
 *  
 *
 *  Project part 3
 *
 */

/* You can use the functions defined in the following files .
 * You cannot use // to make comment because this is a c file.
 */
#include "syscall.h"
#include "userlib.h"

/* Constant values*/
#define MAX_NUM_DOCTORS 3
#define MAX_NUM_NURSES 5
#define MAX_NUM_XTECH 2
#define MAX_NUM_IMAGE 3
#define MAX_NUM_ROOMS 5
#define MAX_NUM_PATIENT 100
#define MAX_NUM_CHILD 50

typedef struct SheetEntry {
	int id;
	int doctorId;
	int examineRoomId;
	int patientSymptom; 
	int state;
	int imageNum;
	int xrayResults[MAX_NUM_IMAGE];
	int shotOrNot;
} SheetEntry;

int startSign;
int test;
int childNum;
int totalPatientNum;
int currentxRayLock;
int currentxRay;
int currentDocLock;
int currentDoc;
int currentNurseLock;
int currentNurse;
int currentPatientLock;
int currentPatient;
int currentChildLock;
int currentChild;

/*variables for examine room*/
int examineRoom[MAX_NUM_ROOMS];/* 1 = NOT_USE, 2 = IN_USE, 3 = NOT_EXIST*/
int wallPocketLock;
struct SheetEntry *wallPocket[MAX_NUM_ROOMS];
int examineRoomPatientLock[MAX_NUM_ROOMS];
int examineRoomPatientCV[MAX_NUM_ROOMS];
int doctorInRoom[MAX_NUM_ROOMS];

/*waiting room nurse*/
int wrnLineLock;
int wrnLineCV;
int wrnLineNum;
int wrnState;/* 1 = AVAILABLE, 2 = UNAVAILABLE, 3 = noExist*/
int wrnLock;
int wrnCV;
int patientAge;
int wrnAction;/* 1 = GIVE_FORM, 2 = ACCEPT_FORM, 3 = GIVE_SHEET, 4 = NO_ACTION*/
int patientIdWithWRN;
int nurseIdWithWRN;
struct MyQueue wrnList;

/*doctor*/
int doctorLock[MAX_NUM_DOCTORS];
int doctorState[MAX_NUM_DOCTORS]; /* 1 = AVAILABLE, 2 = UNAVAILABLE, 3 = noExist*/ 
int doctorCV[MAX_NUM_DOCTORS];
int doctorGoRoomId[MAX_NUM_DOCTORS];
struct SheetEntry *sheetForDoctor[MAX_NUM_DOCTORS];

/*patient*/
int patientLock[MAX_NUM_PATIENT];
int patientCV[MAX_NUM_PATIENT];
int xtIdWithPatient[MAX_NUM_PATIENT];
int patientWithNurse[MAX_NUM_PATIENT];
int patientneedto[MAX_NUM_PATIENT];/* 1 = NEED_EXAMINE, 2 = FINE, 3 = NEED_XRAY, 4 = NEED_SHOT, 5 = XRAY_DONE, 6 = DONE;*/
int symptomResponse[MAX_NUM_PATIENT];/* 1 = PAIN, 2 = NAUSEA, 3 = ALIEN_VOICIES*/
int roomId[MAX_NUM_PATIENT];
struct SheetEntry patientSheets[MAX_NUM_PATIENT];
int isChild[MAX_NUM_PATIENT];

/*child*/
int childLock[MAX_NUM_CHILD];
int childCV[MAX_NUM_CHILD];
int childAction[MAX_NUM_CHILD];/* 1 = FOLLOW, 2 = LEAVE, 3 = XRAY, 4 = SHOT*/

/*cashier*/
int cashierLineLock;
int cashierLineCV;
int cashierLock;
int cashierCV;
int cashierLineNum;
int cashierState;/* 1 = AVAILABLE, 2 = UNAVAILABLE, 3 = noExist*/ 
struct MyQueue cashierList;
int cashierListLock;
int finalMoney[MAX_NUM_PATIENT];

/*xray-technician*/
struct MyQueue xrayFinishList;
struct MyQueue xrayWaitList[MAX_NUM_XTECH];
int xRayTechNum;
int xRayWaitLineLock[MAX_NUM_XTECH];
int xRayWaitLineCV[MAX_NUM_XTECH];
int xRayWaitLineNum[MAX_NUM_XTECH];
int xRayLock[MAX_NUM_XTECH];
int xRayCV[MAX_NUM_XTECH];
int xtechnicianstate[MAX_NUM_XTECH]; /* 1 = AVAILABLE, 2 = UNAVAILABLE, 3 = noExist*/
int xtImageNum[MAX_NUM_XTECH];
int waitListLock[MAX_NUM_XTECH];
int finishListLock;

/*nurse*/
int totalNurseNum;
int patientWaitNum;
int cabinetLock;
int nurseDoctorLock;
int nurseWrnLineCV;
int nurseWrnCount;
struct SheetEntry *sheetForNurse[MAX_NUM_NURSES];

/*adult patient*/
int rand;


/* Functions
 Take rand time to do tasks*/
void doTask() {
	int i;
	int time = ++rand%20+10;
	for (i=0; i<time; i++) {
		Yield();
	}
}

void wait(int number) {
	int i;
	for (i=0; i<number; i++) {
		Yield();
	}
}

void GetForm(int index) {
	int arg[1];
	arg[0] = index;
	AcquireLock(wrnLineLock);	/* Acquire the lock*/
	if (wrnState == 2) {
		/* There are some one before me
		 Increase the number in the line, and wait for my turn*/
		wrnLineNum ++;
		if(test==2 || test==7){
			if (index < childNum){
			  myprintf("Doctor Office 2:Parent[%d] gets in line of the Waiting Room Nurse to get registration form.\n", arg, 1);
		  }
		  else
		  	myprintf("Doctor Office 2:Adult Patient [%d] gets in line of the Waiting Room Nurse to get registration form.\n", arg, 1);
		}
		WaitCondition(wrnLineCV, wrnLineLock);
	}else {
		wrnState = 2;
	}
	AcquireLock(wrnLock);
	ReleaseLock(wrnLineLock);
	/* Now there is nobody in line. Waiting room nurse is available
	 Talk to her directly*/
	wrnAction = 1;	/* Get the form*/
	patientIdWithWRN = index;
	SignalCondition(wrnCV, wrnLock);	/* Wake up the waiting room nurse*/
	WaitCondition(wrnCV, wrnLock);	/* Wait for the form*/
	/* Get the form, go to fill the form*/
	if(test==2 || test==7){
		if (index < childNum){
			myprintf("Doctor Office 2:Parent of child patient[%d] gets the form from the Waiting Room Nurse.\n", arg, 1);
	  }
	  else
	  	myprintf("Doctor Office 2:Adult patient [%d] get the form from the Waiting Room Nurse.\n", arg, 1);
	}
	SignalCondition(wrnCV, wrnLock);	/* Signal the waiting room nurse that I am leaving to fill the form*/
	ReleaseLock(wrnLock);	/* Release the lock and go somewhere*/
}

/* Patient submits form to waiting room nurse*/
void SubmitForm(int index) {
	int arg[1];
	arg[0] = index;
	AcquireLock(wrnLineLock);	/* Acquire the lock*/
	if (wrnState == 2) {
		/* There are some one before me
		 Increase the number in the line, and wait for my turn*/
		wrnLineNum ++;
		if(test==2 || test==7){
			if (index < childNum){
				myprintf("Doctor Office 2:Parent[%d] gets in line of the Waiting Room Nurse to submit registration form.\n", arg, 1);
		  }
		  else
		  	myprintf("Doctor Office 2:Adult Patient [%d] gets in line of the Waiting Room Nurse to submit registration form.\n", arg, 1);
		}
		WaitCondition(wrnLineCV, wrnLineLock);
	}else {
		wrnState = 2;
	}
	AcquireLock(wrnLock);
	ReleaseLock(wrnLineLock);
	/* Now there is nobody in line. Waiting room nurse is available
	 Talk to her directly*/
	wrnAction = 2;	/* Submit the form*/
	patientIdWithWRN = index;
	if(test==2 || test==7){
		if (index < childNum){
			patientAge = 1+(++rand)%18;
			myprintf("Doctor Office 2:Parent of child patient[%d] submits the filled form to the Waiting Room Nurse.\n", arg, 1);
	  }
	  else{
	  	patientAge = 18+(++rand)%62;
	  	myprintf("Doctor Office 2:Adult patient [%d] submit the filled form to the Waiting Room Nurse.\n", arg, 1);
	  }
	}
	SignalCondition(wrnCV, wrnLock);	/* Wake up the waiting room nurse*/
	WaitCondition(wrnCV, wrnLock);	/* Wait for the examination sheet*/
	/* Get the sheet, wait for the nurse*/
	SignalCondition(wrnCV, wrnLock);	/* Signal the waiting room nurse that I am leaving to wait the nurse*/
	AcquireLock(patientLock[index]);	/* Make patient wait for nurse first*/
	ReleaseLock(wrnLock);	/* Release the lock and wait for the nurse*/
	if(test==1||test==2||test==7||test==4)
    myprintf("Doctor Office 2:Parent [%d] waits for a Nurse to escort them to the Xray room.\n", arg, 1);
	WaitCondition(patientCV[index], patientLock[index]);
}


void GoToExamineRoom(int index) {
	/* Follow the nurse*/
	int myRoomId = roomId[index];
	int arg1[1];
	int arg2[2];
	int arg3[3];
	arg1[0] = index;
	arg2[0] = index;
	arg3[0] = index;
	arg2[1] = myRoomId;
	arg3[1] = patientWithNurse[index];
	arg3[2] = myRoomId;
	if (index < childNum){
		childAction[index] = 1;
        AcquireLock(childLock[index]);
        SignalCondition(childCV[index], childLock[index]);
        WaitCondition(childCV[index], childLock[index]);
        ReleaseLock(childLock[index]);
	}
	if(test==2 || test==7 || test==1 || test==4 || test==5){
		if (index >= childNum){
			myprintf("Doctor Office 2:Adult Patient [%d] is following Nurse [%d] to Examination Room [%d].\n", arg3, 3);
    }
	}
	if(test==1||test==4||test==7||test==2){
		if (index < childNum){
        myprintf("Doctor Office 2:Parent[%d] is following Nurse[%d] to Examination Room[%d].\n", arg3, 3);
	  }
  }
	SignalCondition(patientCV[index], patientLock[index]);
	WaitCondition(patientCV[index], patientLock[index]);
	if(test==2 || test==7 || test==1 || test==4 || test==5){
		if (index >= childNum){
			myprintf("Doctor Office 2:Adult Patient [%d] has arrived at Examination Room [%d].\n", arg2, 2);
	  }
	}
	if(test==1||test==4||test==7||test==2){
		if (index < childNum){
       myprintf("Doctor Office 2:Parent[%d] has arrived at Examination Room [%d].\n", arg2, 2);
	  }
	}
	/* Get into the examine room and interact with nurse*/
	SignalCondition(patientCV[index], patientLock[index]);
	WaitCondition(patientCV[index], patientLock[index]);
	symptomResponse[index] = ++rand%3;
	switch (symptomResponse[index]) {
		case 1:
			if(test == 7 && index >= childNum)
				myprintf("Doctor Office 2:Adult Patient [%d] says, My symptoms are Pain\n", arg1, 1);
      if((test==1||test==7) && index < childNum)
        myprintf("Doctor Office 2:Parent [%d] says, \"His symptoms are Pain\".\n", arg1, 1);
			break;
		case 2:
			if(test == 7 && index >= childNum)
				myprintf("Doctor Office 2:Adult Patient [%d] says, My symptoms are Nausea\n", arg1, 1);
			if((test==1||test==7) && index < childNum)
				myprintf("Doctor Office 2:Parent [%d] says, \"His symptoms are Nausea\".\n", arg1, 1);
			break;
		case 3:
			if(test == 7 && index >= childNum)
				myprintf("Doctor Office 2:Adult Patient [%d] says, My symptoms are Hear Alien Voices\n", arg1, 1);
			if((test==1||test==7) && index < childNum)
				myprintf("Doctor Office 2:Parent [%d] says, \"His symptoms are Hear Alien Voices\".\n", arg1, 1);
			break;
		default:
			break;
	}
	SignalCondition(patientCV[index], patientLock[index]);
	WaitCondition(patientCV[index], patientLock[index]);
	/* Wait for the doctor
	 Make sure the patient will wait for the doctor first*/
	AcquireLock(examineRoomPatientLock[myRoomId]);
	SignalCondition(patientCV[index], patientLock[index]);
	ReleaseLock(patientLock[index]);
	/* Patient wait for the doctor*/
	WaitCondition(examineRoomPatientCV[myRoomId], examineRoomPatientLock[myRoomId]);
}

void BackToExamineRoom(int index) {
	/* Follow the nurse
	 Make sure the patient will wait for the doctor first*/
	if (index < childNum){
		AcquireLock(childLock[index]);
    SignalCondition(childCV[index], childLock[index]);
    WaitCondition(childCV[index], childLock[index]);
    ReleaseLock(childLock[index]);
    SignalCondition(patientCV[index], patientLock[index]);
    WaitCondition(patientCV[index], patientLock[index]);
	}
	AcquireLock(examineRoomPatientLock[roomId[index]]);
	SignalCondition(patientCV[index], patientLock[index]);
	ReleaseLock(patientLock[index]);
	/* Patient wait for the doctor*/
	WaitCondition(examineRoomPatientCV[roomId[index]], examineRoomPatientLock[roomId[index]]);
}

void GetShot(int index) {
	/* Patient is told she need a shot*/
	int myRoomId = roomId[index];
	int arg[1];
	arg[0] = index;
	ReleaseLock(examineRoomPatientLock[myRoomId]);
	AcquireLock(patientLock[index]);
	/* Wait nurse to get the medicine*/
	if(test == 7 && index >= childNum)
		myprintf("Doctor Office 2:Adult Patient [%d] says, \"Yes I am ready for the shot\".\n", arg, 1);
	if((test==1||test==7) && index < childNum )
		myprintf("Doctor Office 2:Parent [%d] says, \"Yes He is ready for the shot\".\n", arg, 1);
	SignalCondition(patientCV[index], patientLock[index]);
	WaitCondition(patientCV[index], patientLock[index]);
	/* The shot is done*/
	if(test==7)
    myprintf("Doctor Office 2:Child patient [%d] has been given a shot.\n", arg, 1);
	SignalCondition(patientCV[index], patientLock[index]);
	AcquireLock(examineRoomPatientLock[myRoomId]);
	ReleaseLock(patientLock[index]);
	/* Wait the nurse to take me to the cashier*/
	WaitCondition(examineRoomPatientCV[myRoomId], examineRoomPatientLock[myRoomId]);
}

void takexRay(int index){
	int roomNum;
	int imageNum;
	int arg[1];
	int i;
	arg[0] = index;
	if((test == 7 || test==4||test==5) && index >= childNum)
        myprintf("Doctor Office 2:Adult Patient [%d] waits for a Nurse to escort them to Xray room.\n", arg, 1);
	if((test==1||test==7||test==4) && index < childNum)
		    myprintf("Doctor Office 2:Parent[%d] waits for a Nurse to escort them to the Xray room.\n",  arg, 1);
	SignalCondition(examineRoomPatientCV[roomId[index]], examineRoomPatientLock[roomId[index]]);
	if (index < childNum){
		childAction[index] = 1;
    AcquireLock(childLock[index]);
    SignalCondition(childCV[index], childLock[index]);
    WaitCondition(childCV[index], childLock[index]);
    ReleaseLock(childLock[index]);
	}
	AcquireLock(patientLock[index]);
	ReleaseLock(examineRoomPatientLock[roomId[index]]);
	WaitCondition(patientCV[index], patientLock[index]);
	/*Patient goes to the waiting room of xray room*/
	roomNum = xtIdWithPatient[index];
	AcquireLock(xRayWaitLineLock[roomNum]);
	SignalCondition(patientCV[index], patientLock[index]);
	ReleaseLock(patientLock[index]);
	if (xtechnicianstate[roomNum] == 2){
		/*there are someone in front of the patient,he has to wait */
		xRayWaitLineNum[roomNum]++;
		WaitCondition(xRayWaitLineCV[roomNum], xRayWaitLineLock[roomNum]);
	}
	else {
		xtechnicianstate[roomNum] = 2;
	}
	ReleaseLock(xRayWaitLineLock[roomNum]);
	AcquireLock(xRayLock[roomNum]);
	SignalCondition(xRayCV[roomNum], xRayLock[roomNum]);
	WaitCondition(xRayCV[roomNum], xRayLock[roomNum]);
	if(test==7){
		if (index >= childNum)
      myprintf("Doctor Office 2:Adult Patient [%d] gets on the table.\n", arg, 1);
    else
    	myprintf("Doctor Office 2:Child Patient [%d] gets on the table.\n", arg, 1);
	}
	SignalCondition(xRayCV[roomNum], xRayLock[roomNum]);
	if(test==7){
		if (index >= childNum)
      myprintf("Doctor Office 2:Adult Patient [%d] has been asked to take an Xray.\n", arg, 1);
	  else
	  	myprintf("Doctor Office 2:Child Patient [%d] has been asked to take an Xray.\n", arg, 1);
	}
	imageNum = xtImageNum[roomNum];
	for (i=0; i<imageNum-1; i++){
		WaitCondition(xRayCV[roomNum], xRayLock[roomNum]);
		if(test==7)
      myprintf("Doctor Office 2:Child Patienht [%d] moves for the next Xray.\n", arg, 1);
		SignalCondition(xRayCV[roomNum], xRayLock[roomNum]);
	}
	WaitCondition(xRayCV[roomNum], xRayLock[roomNum]);
	SignalCondition(xRayCV[roomNum], xRayLock[roomNum]);
	AcquireLock(patientLock[index]);
	ReleaseLock(xRayLock[roomNum]);
	/*patient wait in the finish xray waiting room  */
	WaitCondition(patientCV[index], patientLock[index]);
}

/* Patient interacts with doctor*/
void InteractWithDoctor(int index){
	int arg[2];
	int myRoomId = roomId[index];
	int doctorId = doctorInRoom[myRoomId];
	arg[0] = index;
	arg[1] = doctorId;
	AcquireLock(doctorLock[doctorId]);
	ReleaseLock(examineRoomPatientLock[myRoomId]);
	SignalCondition(doctorCV[doctorId], doctorLock[doctorId]);
	WaitCondition(doctorCV[doctorId], doctorLock[doctorId]);
	if(test==7||test==6){
		if (index >= childNum){
			myprintf("Doctor Office 2:Adult Patient [%d] has been diagnosed by Doctor [%d].\n", arg, 2);
	  }
	  else
	  	myprintf("Doctor Office 2:Child Patient [%d] has been diagnosed by Doctor [%d].\n", arg, 2);
	}
	if (patientneedto[index] == 3){
		if(test==7||test==6){
			if (index >= childNum){
				myprintf("Doctor Office 2:Adult Patient [%d] has been informed by Doctor [%d] that he needs an Xray.\n", arg, 2);
	    }
	    else
	    	myprintf("Doctor Office 2:Child Patient [%d] has been informed by Doctor [%d] that he needs an Xray.\n", arg, 2);
	  }
	}
	if (patientneedto[index] == 4){
		if(test==7||test==6){
			if (index >= childNum){
				myprintf("Doctor Office 2:Adult Patient [%d] has been informed by Doctor [%d] that he will be administered a shot.\n", arg, 2);
	    }
	    else
	    	myprintf("Doctor Office 2:Child Patient [%d] has been informed by Doctor [%d] that he will be administered a shot.\n", arg, 2);
	  }
	}
	SignalCondition(doctorCV[doctorId], doctorLock[doctorId]);
	AcquireLock(examineRoomPatientLock[myRoomId]);
	ReleaseLock(doctorLock[doctorId]);
	WaitCondition(examineRoomPatientCV[myRoomId], examineRoomPatientLock[myRoomId]);
}

/* Patient pays money to the cashier*/
void PayMoney(int index) {
	int arg[2];
	arg[0] = index;
	if (index >= childNum)
	  ReleaseLock(examineRoomPatientLock[roomId[index]]);
	if (index < childNum){
		childAction[index] = 1;
    AcquireLock(childLock[index]);
    SignalCondition(childCV[index], childLock[index]);
    WaitCondition(childCV[index], childLock[index]);
    ReleaseLock(childLock[index]);
    SignalCondition(examineRoomPatientCV[roomId[index]], examineRoomPatientLock[roomId[index]]);
    WaitCondition(examineRoomPatientCV[roomId[index]], examineRoomPatientLock[roomId[index]]);
        
    ReleaseLock(examineRoomPatientLock[roomId[index]]);
	}
	AcquireLock(cashierLineLock);
	if (cashierState != 1) {
		/* The cashier is not available wait in the line*/
		cashierLineNum ++;
		if((test==3||test==7) && index >= childNum)
			myprintf("Doctor Office 2:Adult Patient [%d] enters the queue for Cashier\n", arg, 1);
		if((test==1||test==7||test==3||test==4) && index < childNum)
			myprintf("Doctor Office 2:Parent[%d] enters the queue for Cashier.\n", arg, 1);
		WaitCondition(cashierLineCV, cashierLineLock);
	}else {
		cashierState = 2;
	}
	
	AcquireLock(cashierLock);
	ReleaseLock(cashierLineLock);
	/* If the cashier is available, walk to the cashier*/
	if(test==3||test==7){
		if(index >= childNum){
			myprintf("Doctor Office 2:Adult Patient [%d] reaches the Cashier.\n",  arg, 1);
			myprintf("Doctor Office 2:Adult Patient [%d] hands over his examination sheet to the Cashier.\n", arg, 1);
	  }
	  else{
	  	myprintf("Doctor Office 2:Parent [%d] reaches the Cashier.\n", arg, 1);
      myprintf("Doctor Office 2:Parent [%d] hands over his examination sheet to the Cashier.\n",  arg, 1);
	  }
	}
	/* Wait cashier determine the fee*/
	SignalCondition(cashierCV, cashierLock);
	WaitCondition(cashierCV, cashierLock);
	arg[1] = finalMoney[index];
	if(test==3||test==7){
		if(index >= childNum)
			myprintf("Doctor Office 2:Adult Patient [%d] pays the Cashier $ %d \n", arg, 2);
	  else
	  	myprintf("Doctor Office 2:Parent [%d] pays the Cashier $ %d \n",  arg, 2);
	}
	/* Wait for the receipt*/
	SignalCondition(cashierCV, cashierLock);
	WaitCondition(cashierCV, cashierLock);
	arg[1] = index;
	if(test==3||test==7){
		if(index >= childNum)
			myprintf("Doctor Office 2:Adult Patient [%d] receives a receipt from the Cashier.\n",  arg, 1);
	  else
	  	myprintf("Doctor Office 2:Parent [%d] receives a receipt for Child Patient[%d] from the Cashier.\n", arg, 2);
	}
	SignalCondition(cashierCV, cashierLock);
	if((test==3||test==7||test==5) && index >= childNum)
		myprintf("Doctor Office 2:Adult Patient [%d] leaves the doctor's office.\n", arg, 1);
	if((test==1||test==7||test==3||test==5) && index < childNum)
		myprintf("Doctor Office 2:Parent [%d] leaves the doctor's office with Child Patient[%d].\n", arg, 2);
	totalPatientNum --;
	ReleaseLock(cashierLock);
}

void AdultPatient(){
	int index;
	int patientaction;
	int arg[2];
	AcquireLock(currentPatientLock);
	if(currentPatient == 0) {
		myprintf("Doctor Office 2:I'm the first patient\n", 0, 0);
	}
	if(currentPatient == 3) {
		myprintf("Doctor Office 2:I'm patient No.3 \n", 0, 0);
	}
	index = currentPatient;
	currentPatient++;
	ReleaseLock(currentPatientLock);
	arg[0] = index;
	arg[1] = index;
	while (startSign > 0) {
		/* Check the start signal to see if I can start*/
		wait(5);
	}
	
	/* A patient gets into the office*/
	if(index < childNum){
  myprintf("Doctor Office 2:Child Patient [%d] has entered the Doctor's Office Waiting Room with Parent [%d].\n", arg, 2);
  }
  else{
	myprintf("Doctor Office 2:Adult Patient [%d] has entered the Doctor's Office Waiting Room.\n", arg, 1);
  }
	/* First, he has to interact with the waiting room nurse to get a form*/
	GetForm(index);
	/* The patient fills the form*/
	doTask();
	/* He comes back to the waiting room nurse to submit the form*/
	SubmitForm(index);
	/* The patient is waiting for the nurse to call him*/
	GoToExamineRoom(index);
	InteractWithDoctor(index);
	while (1) {
		patientaction = patientneedto[index];
		if (patientaction == 3){
			takexRay(index);
		}
		else if (patientaction == 4){
			GetShot(index);
		}
		else if (patientaction == 5) {
			BackToExamineRoom(index);
			InteractWithDoctor(index);
		}
		else if (patientaction == 6){
			break;
		}
	}	
	PayMoney(index);
	Exit(0);
}

void ChildPatient() {
	int index;
	int arg[2];
	AcquireLock(currentChildLock);
	index = currentChild++;
	isChild[index] = 1;
	ReleaseLock(currentChildLock);
	arg[0] = index;
	arg[1] = index;
	while (1) {
		AcquireLock(childLock[index]);
		WaitCondition(childCV[index], childLock[index]);
		/* Wait for parent telling them to follow*/
		if (childAction[index] == 1) {
			if(test==1 || test==4||test==7)
				myprintf("Doctor Office 2:Parent[%d] asks Child Patient[%d] to follow them.\n", arg , 2);
			SignalCondition(childCV[index], childLock[index]);
		}else if (childAction[index] == 2) {
			SignalCondition(childCV[index], childLock[index]);
			ReleaseLock(childLock[index]);
			break;
		}
		ReleaseLock(childLock[index]);
	}
	Exit(0);
}


void WaitingRoomNurse() {
	/* Make sure the thread is executed before patient threads*/
	int arg1[1];
	int arg2[2];
	int arg3[2];
	int i;
	int nurseId;
	int patientId;
	while (1) {
		AcquireLock(wrnLineLock);
		/* Check if there are nurses waiting*/
		if (nurseWrnCount == 0 && wrnLineNum == 0) {
			/* No nurse, No patient*/
			wrnState = 1;
		}else if (nurseWrnCount > 0) {
			/* Nurse waiting and there are patients waiting for the nurse
			 Wake up the nurse*/
			SignalCondition(nurseWrnLineCV, wrnLineLock);
			nurseWrnCount --;
			wrnState = 2;
		}else if (wrnLineNum > 0) {
			SignalCondition(wrnLineCV, wrnLineLock);
			wrnLineNum --;  /* Decrease the number of patients in the line*/
			wrnState = 2;
		}
		AcquireLock(wrnLock);
		startSign --;
		ReleaseLock(wrnLineLock);
		WaitCondition(wrnCV, wrnLock);  /* Wait for someone coming*/
		/* Patient comes*/
		switch (wrnAction) {
			case 1:
				patientId = patientIdWithWRN;
				arg1[0] = patientId;
				if (patientId < childNum){
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse gives a form to the Parent of Child patient [%d].\n", arg1, 1);
				}
				else{
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse gives a form to Adult patient [%d].\n", arg1, 1);
				}
				SignalCondition(wrnCV, wrnLock);
				WaitCondition(wrnCV, wrnLock);
				ReleaseLock(wrnLock);
				break;
			case 2:
				patientId = patientIdWithWRN;
				arg1[0] = patientId;
				arg2[0] = patientId;
				arg2[1] = patientAge;
				if (patientId < childNum){
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse accepts the form from Parent with name [%d] and age [%d].\n", arg2, 2);
				}
				else{
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse accepts the form from Adult Patient with name [%d] and age [%d].\n", arg2, 2);                         
				}
				patientSheets[patientId].id = patientId;
				patientSheets[patientId].state = 1;
				InQueue(&wrnList, &patientSheets[patientId]);
				if (patientId < childNum){
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse creates an examination sheet for Child patient with name [%d] and age [%d].\n", arg2, 2);
				}
				else{
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse creates an examination sheet for Adult patient with name [%d] and age [%d].\n", arg2, 2);                              
				}
				if (patientId < childNum){
					if(test==1||test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse tells the Parent [%d] to wait in the waiting room for a nurse.\n",  arg1, 1);
				}
				else{
					if(test==7||test==2)
						myprintf("Doctor Office 2:Waiting Room nurse tells the Adult Patient [%d] to wait in the waiting room for a nurse.\n", arg1, 1);                                
				}
				patientWaitNum ++;
				SignalCondition(wrnCV, wrnLock);
				WaitCondition(wrnCV, wrnLock);
				ReleaseLock(wrnLock);
				break;
			case 3:
				nurseId = nurseIdWithWRN;
				sheetForNurse[nurseId] = (SheetEntry *) DeQueue(&wrnList);
				arg3[0] = sheetForNurse[nurseId]->id;
				arg3[1] = nurseId;
				if(test==7||test==2)
					myprintf("Doctor Office 2:Waiting Room nurse gives examination sheet of patient[%d] to Nurse[%d].\n", arg3, 2);
				SignalCondition(wrnCV, wrnLock);
				WaitCondition(wrnCV, wrnLock);
				ReleaseLock(wrnLock);
				break;
			case 4:
				break;
			default:
				Write("Error: Unkown states in WaitingRoomNurse\n", 32,  ConsoleOutput);
				break;
		}
	}
	Exit(0);
}

/* Find a available examine room*/
int FindExamineRoom() {      
	int found = -1;
	int i;
	AcquireLock(wallPocketLock);
	for (i=0; i<MAX_NUM_ROOMS; i++) {
		if (examineRoom[i] == 1) {
			examineRoom[i] = 2;        /* Occupy the room*/
			found = i;
			break;
		}
	}
	ReleaseLock(wallPocketLock);
	return found;
}

/* Release an examine room*/
void ReleaseExamineRoom(int index) {
	int arg[1];
	arg[0] = index;
	AcquireLock(wallPocketLock);
	if (examineRoom[index] != 3) {
		examineRoom[index] = 1;
	}else {
		myprintf("Doctor Office 2:Error: examine room %d doesn't exist\n", arg, 1);
	}
	ReleaseLock(wallPocketLock);
}

int FindAvailableDoctor() {
	int doctorId = -1;
	int i;
	AcquireLock(nurseDoctorLock);
	for (i=0; i<MAX_NUM_DOCTORS; i++) {
		if (doctorState[i] == 1) {
			doctorId = i;
			doctorState[i] = 2;
			break;
		}
	}
	ReleaseLock(nurseDoctorLock);
	return doctorId;
}

void CallDoctor(int index, int examineRoomId, SheetEntry *myLocalSheet) {
	/* Find an available doctor*/
	int doctorId = FindAvailableDoctor();
	int arg1[3];
	int arg2[4];
	arg1[0] = index;
	arg2[0] = index;
	arg1[1] = doctorId;
	arg2[1] = doctorId;
	arg1[2] = myLocalSheet->id;
	arg2[2] = myLocalSheet->id;
	arg2[3] = examineRoomId;
	if (doctorId >= 0) {
		/* There is an available doctor*/
		AcquireLock(doctorLock[doctorId]);
		/* Tell the doctor which room to go*/
		doctorGoRoomId[doctorId] = examineRoomId;
		/* Wake up the doctor*/
		SignalCondition(doctorCV[doctorId], doctorLock[doctorId]);
		if (myLocalSheet->id < childNum){
			if(test==1||test==7||test==6)
				myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Child Patient [%d] is waiting in the examination room [%d].\n", arg2, 4);
		}
		else{
			if(test==7||test==6)
				myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Adult Patient [%d] is waiting in the examination room [%d].\n", arg2, 4);
		}
		/* Give doctor the examine sheet*/
		myLocalSheet->doctorId = doctorId;
		sheetForDoctor[doctorId] = myLocalSheet;
		if (myLocalSheet->id < childNum){
			if(test==7||test==6)
				myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Child Patient [%d].\n", arg1, 3);
		}
		else{
			if(test==7||test==6)
				myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Adult Patient [%d].\n", arg1, 3);	  	
		}
		ReleaseLock(doctorLock[doctorId]);
	}else {
		/* No doctor available, put the sheet in the wall pocket*/
		AcquireLock(wallPocketLock);
		wallPocket[examineRoomId] = myLocalSheet;
		ReleaseLock(wallPocketLock);
	}
}

void Nurse() {
	/* Make sure the thread is executed before patient threads*/
	int index;
	int doctorId;
	int arg1[1];
	int arg2[2];
	int arg3[3];
	int arg4[4];
	int xtechId;
	int examineRoomId;
	int i;
	struct SheetEntry *myLocalSheet;
	AcquireLock(currentNurseLock);
	index = currentNurse ++;
	ReleaseLock(currentNurseLock);
	arg1[0] = index;
	arg2[0] = index;
	arg3[0] = index;
	arg4[0] = index;
	while (startSign > 0) {
		wait(2);
	}
	while (totalPatientNum > 0) {
		examineRoomId = FindExamineRoom();
		if (examineRoomId >= 0) {
			/* If there is an open examination room
			 Task 1: Get patient from waiting room, escort to exam room
			 Nurse will ask waiting room nurse whether there is any patient waiting for examination*/
			AcquireLock(wrnLineLock);
			if (wrnState == 2) {
				nurseWrnCount ++;
				WaitCondition(nurseWrnLineCV, wrnLineLock);
			}else {
				wrnState = 2;
			}
			if (patientWaitNum > 0) {
				/* There are some patients waiting for examination
				 Waiting room nurse gives the examination sheet to the nurse*/
				patientWaitNum --;
				AcquireLock(wrnLock);
				ReleaseLock(wrnLineLock);
				/* Tell the waiting room nurse to give a sheet*/
				if(test==7||test==2)
					myprintf("Doctor Office 2:Nurse[%d] tells Waiting Room Nurse to give a new examination sheet.\n", arg1, 1);
				nurseIdWithWRN = index;
				wrnAction = 3;
				SignalCondition(wrnCV, wrnLock);
				/*Wait for the sheet*/
				WaitCondition(wrnCV, wrnLock);
				myLocalSheet = sheetForNurse[index];
				arg2[1] = myLocalSheet->id;
				arg3[1] = myLocalSheet->id;
				arg3[2] = examineRoomId;
				SignalCondition(wrnCV, wrnLock);
				AcquireLock(patientLock[myLocalSheet->id]);
				ReleaseLock(wrnLock);
				/* Nurse calls the patient to follow her*/
				roomId[myLocalSheet->id] = examineRoomId;
				patientWithNurse[myLocalSheet->id] = index;
				SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				/* Nurse takes the patient to the examination room*/
				if (myLocalSheet->id < childNum){
					if(test==7||test==1||test==4)
						myprintf("Doctor Office 2:Nurse [%d] escorts Parent [%d] to the examination room [%d].\n", arg3, 3);
				}
				else{
					if(test==7||test==4)
						myprintf("Doctor Office 2:Nurse [%d] escorts Adult Patient [%d] to the examination room [%d].\n", arg3, 3);
				}
				SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				/* Take temperature, blood pressure*/
				if (myLocalSheet->id < childNum){
					if(test==7){
						myprintf("Doctor Office 2:Nurse [%d] takes the temperature and blood pressure of Child [%d].\n", arg2, 2);
						/* Ask sympton*/
						myprintf("Doctor Office 2:Nurse [%d] asks Parent [%d] \"What Symptoms do you have?\"\n", arg2, 2);
					}
				}
				else{
					if(test==7){
						myprintf("Doctor Office 2:Nurse [%d] takes the temperature and blood pressure of Adult Patient [%d].\n", arg2, 2);
						/* Ask sympton*/
						myprintf("Doctor Office 2:Nurse [%d] asks Adult Patient [%d] \"What Symptoms do you have?\"\n", arg2, 2);
					}
				}
				SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				/* Wait for patient's response;*/
				WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				/* Write the sympton on the examine sheet*/
				myLocalSheet->patientSymptom = symptomResponse[myLocalSheet->id];
				if (myLocalSheet->id < childNum){
					if(test==7)
						myprintf("Doctor Office 2:Nurse [%d] writes all the information of Child [%d] in his examination sheet.\n", arg2, 2);
				}
				else{
					if(test==7)
						myprintf("Doctor Office 2:Nurse [%d] writes all the information of Adult Patient [%d] in his examination sheet.\n", arg2, 2);                             
				}
				SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				ReleaseLock(patientLock[myLocalSheet->id]);
				/* Call the doctor*/
				CallDoctor(index, examineRoomId, myLocalSheet);
			}else {
				AcquireLock(wrnLock);
				ReleaseLock(wrnLineLock);
				wrnAction = 4;
				SignalCondition(wrnCV, wrnLock);
				ReleaseLock(wrnLock);
				ReleaseExamineRoom(examineRoomId);
			}
		}
		doTask();
		/* Task 2: Escort patient back to exam room*/
		AcquireLock(finishListLock);
		if (xrayFinishList.number != 0) {
			myLocalSheet = (SheetEntry *)DeQueue(&xrayFinishList);
			arg2[1] = myLocalSheet->id;
			if (myLocalSheet->id < childNum){
				if(test==7||test==1)
					myprintf("Doctor Office 2:Nurse [%d] gets examination sheet for Parent [%d] in Xray waiting room.\n", arg2, 2);
			}
			else{
				if(test==7)
					myprintf("Doctor Office 2:Nurse [%d] gets examination sheet for Adult Patient [%d] in Xray waiting room.\n", arg2, 2);
			}
			myLocalSheet->state = 5;
			ReleaseLock(finishListLock);
			AcquireLock(patientLock[myLocalSheet->id]);
			/* Tell patient back to the examine room*/
			patientneedto[myLocalSheet->id] = 5;
			/*YJ add*/
			examineRoomId = roomId[myLocalSheet->id];
			if (myLocalSheet->id < childNum){
				SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
				arg3[1] = myLocalSheet->id;
				arg3[2] = examineRoomId;
				if(test==7||test==1||test==4)
					myprintf("Doctor Office 2:Nurse [%d] escorts Parent [%d] to the examination room [%d].\n",  arg3, 3);
			}
			else{
				if(test==7||test==4)
					myprintf("Doctor Office 2:Nurse [%d] escorts Adult Patient [%d] to the examination room [%d].\n", arg3, 3);                        
			}
			SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
			WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
			ReleaseLock(patientLock[myLocalSheet->id]);
			/* Call the doctor*/
			doctorId = myLocalSheet->doctorId;
			AcquireLock(nurseDoctorLock);
			if (doctorState[doctorId] == 1) {
				doctorState[doctorId] = 2;
			}else {
				doctorId = -1;
			}
			ReleaseLock(nurseDoctorLock);
			if (doctorId >=0) {
				/* The doctor is available*/
				AcquireLock(doctorLock[doctorId]);
				/* Tell the doctor which room to go*/
				doctorGoRoomId[doctorId] = myLocalSheet->examineRoomId;
				/* Wake up the doctor*/
				SignalCondition(doctorCV[doctorId], doctorLock[doctorId]);
				arg4[1] = doctorId;
				arg4[2] = myLocalSheet->id;
				arg4[3] = myLocalSheet->examineRoomId;
				if (myLocalSheet->id < childNum){
					if(test==7||test==6)
						myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Child Patient [%d] is waiting in the examination room [%d].\n", arg4, 4);
				}
				else{
					if(test==7||test==6)
						myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Adult Patient [%d] is waiting in the examination room [%d].\n", arg4, 4);                            
				}
				/* Give doctor the examine sheet*/
				myLocalSheet->doctorId = doctorId;
				sheetForDoctor[doctorId] = myLocalSheet;
				arg3[1] = doctorId;
				arg3[2] = myLocalSheet->id;
				if (myLocalSheet->id < childNum){
					if(test==7||test==6)
						myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Child Patient [%d].\n", arg3, 3);
				}
				else{
					if(test==7||test==6)
						myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Adult Patient [%d].\n", arg3, 3);                           
				}
				ReleaseLock(doctorLock[doctorId]);
			}else {
				/* The doctor is not available, put the sheet in the wall pocket*/
				AcquireLock(wallPocketLock);
				wallPocket[examineRoomId] = myLocalSheet;
				ReleaseLock(wallPocketLock);
			}
		}else {
			ReleaseLock(finishListLock);
		}
		doTask();
		/* Task 3: Check wall pocket outside the room*/
		examineRoomId = -1;
		AcquireLock(wallPocketLock);
		for (i=0; i<MAX_NUM_ROOMS; i++) {
			if (wallPocket[i] != 0) {
				examineRoomId = i;
				myLocalSheet = wallPocket[i];
				wallPocket[i] = 0;
				break;
			}
		}
		ReleaseLock(wallPocketLock);
		if (examineRoomId >=0 ) {
			/* There is an examine sheet in the wall pocket*/
			arg2[1] = examineRoomId;
			if(test==7||test==4)
				myprintf("Doctor Office 2:Nurse [%d] checks the wall box of examination room[%d]\n", arg2, 2);
			/* Take different actions according to the patient's state in the examination room*/
			switch (myLocalSheet->state) {
				case 3:
					/* Tell patient to follow to take xray*/
					patientneedto[myLocalSheet->id] = 3;
					AcquireLock(examineRoomPatientLock[examineRoomId]);
					SignalCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
					WaitCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
					ReleaseLock(examineRoomPatientLock[examineRoomId]);
					AcquireLock(patientLock[myLocalSheet->id]);
					xtechId = ++rand%xRayTechNum;
					arg3[1] = myLocalSheet->id;
					arg3[2] = xtechId;
					/* Wait the patient
					 Take patient to the Xray Technician*/
					if (myLocalSheet->id < childNum){
						if(test==7||test==1||test==4)
							myprintf("Doctor Office 2:Nurse [%d] escorts Parent [%d] to the X-ray room [%d]\n", arg3, 3);
					}
					else{
						if(test==7||test==4)
							myprintf("Doctor Office 2:Nurse [%d] escorts Adult Patient [%d] to the X-ray room [%d]\n", arg3, 3);                                     
					}
					/* Put the examination sheet in the pocket*/
					myLocalSheet->examineRoomId = examineRoomId;
					AcquireLock(waitListLock[xtechId]);
					if (myLocalSheet->id < childNum){
						if(test==7)
							myprintf("Doctor Office 2:Nurse [%d] informs X-Ray Technician [%d] about Child Patient [%d] and hands over the examination sheet.\n", arg3, 3);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Nurse [%d] informs X-Ray Technician [%d] about Adult Patient [%d] and hands over the examination sheet.\n", arg3, 3);                                          
					}
					InQueue(&xrayWaitList[xtechId], myLocalSheet);
					xtIdWithPatient[myLocalSheet->id] = xtechId;
					SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
					WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
					if(test==7)
						myprintf("Doctor Office 2:Nurse [%d] leaves the X-ray waiting Room.\n", arg1, 1);
					ReleaseLock(patientLock[myLocalSheet->id]);
					ReleaseLock(waitListLock[xtechId]);
					break;
				case 5:
					arg2[1] = myLocalSheet->id;
					doctorId = myLocalSheet->doctorId;
					AcquireLock(nurseDoctorLock);
					if (doctorState[doctorId] == 1) {
						doctorState[doctorId] = 2;
					}else {
						doctorId = -1;
					}
					ReleaseLock(nurseDoctorLock);
					if (doctorId >=0) {
						/* The doctor is available*/
						AcquireLock(doctorLock[doctorId]);
						/* Tell the doctor which room to go*/
						doctorGoRoomId[doctorId] = examineRoomId;
						/* Wake up the doctor*/
						SignalCondition(doctorCV[doctorId], doctorLock[doctorId]);
						arg4[1] = doctorId;
						arg4[2] = myLocalSheet->id;
						arg4[3] = examineRoomId;
						if (myLocalSheet->id < childNum){
							if(test==7||test==6)
								myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Child Patient [%d] is waiting in the examination room [%d].\n", arg4, 4);
						}
						else{
							if(test==7||test==6)
								myprintf("Doctor Office 2:Nurse [%d] informs Doctor [%d] that Adult Patient [%d] is waiting in the examination room [%d].\n", arg4, 4);                                          
						}
						/* Give doctor the examine sheet*/
						myLocalSheet->doctorId = doctorId;
						sheetForDoctor[doctorId] = myLocalSheet;
						arg3[1] = doctorId;
						arg3[2] = myLocalSheet->id;
						if (myLocalSheet->id < childNum){
							if(test==7||test==6)
								myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Child Patient [%d].\n", arg3, 3);
						}
						else{
							if(test==7||test==6)
								myprintf("Doctor Office 2:Nurse [%d] hands over to the Doctor [%d] the examination sheet of Adult Patient [%d].\n", arg3, 3);                                           
						}
						ReleaseLock(doctorLock[doctorId]);
					}else {
						/* The doctor is not available, put the sheet in the wall pocket*/
						AcquireLock(wallPocketLock);
						wallPocket[examineRoomId] = myLocalSheet;
						ReleaseLock(wallPocketLock);
					}
					break;
				case 1:
					/* Need Doctor*/
					CallDoctor(index, examineRoomId, myLocalSheet);
					break;
				case 4:
					AcquireLock(examineRoomPatientLock[examineRoomId]);
					/* Wake up the patient*/
					SignalCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
					AcquireLock(patientLock[myLocalSheet->id]);
					patientneedto[myLocalSheet->id] = 4;
					ReleaseLock(examineRoomPatientLock[examineRoomId]);
					/* Get medicine*/
					AcquireLock(cabinetLock);
					arg2[1] = myLocalSheet->id;
					if (myLocalSheet->id < childNum){
						if(test==7||test==1)
							myprintf("Doctor Office 2:Nurse [%d] goes to supply cabinet to give to take medicine for Parent [%d].\n", arg2, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Nurse [%d] goes to supply cabinet to give to take medicine for Adult Patient [%d].\n", arg2, 2);                                        
					}
					ReleaseLock(cabinetLock);
					if (myLocalSheet->id < childNum){
						if(test==7||test==1)
							myprintf("Doctor Office 2:Nurse [%d] asks Parent [%d] \"Whether you are ready for the shot?\"\n", arg2, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Nurse [%d] asks Adult Patient [%d] \"Whether you are ready for the shot?\"\n", arg2, 2);                                        
					}
					WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
					/* Shot
					 Shot over*/
					if (myLocalSheet->id < childNum){
						if(test==7||test==1)
							myprintf("Doctor Office 2:Nurse [%d] tells Parent [%d] \"Shot is over.\"\n", arg2, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Nurse [%d] tells Adult Patient [%d] \"Shot is over.\"\n", arg2, 2);                                     
					}
					myLocalSheet->shotOrNot = 1;
					myLocalSheet->state = 6;
					SignalCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
					WaitCondition(patientCV[myLocalSheet->id], patientLock[myLocalSheet->id]);
					ReleaseLock(patientLock[myLocalSheet->id]);
				case 2:
				case 6:
					AcquireLock(examineRoomPatientLock[examineRoomId]);
					/* Tell patient to follow*/
					patientneedto[myLocalSheet->id] = 6;
					/* Take the patient to the cashier*/
					if (myLocalSheet->id < childNum){
						SignalCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
						WaitCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
						if(test==7||test==4||test==1)
							myprintf("Doctor Office 2:Nurse [%d] escorts Parent [%d] to Cashier.\n", arg2, 2);
					}
					else{
						if(test==7||test==4)
							myprintf("Doctor Office 2:Nurse [%d] escorts Adult Patient [%d] to Cashier.\n", arg2, 2);
					}
					AcquireLock(cashierListLock);
					InQueue(&cashierList, myLocalSheet);		
					SignalCondition(examineRoomPatientCV[examineRoomId], examineRoomPatientLock[examineRoomId]);
					ReleaseLock(examineRoomPatientLock[examineRoomId]);
					/* Release the examine room*/
					ReleaseExamineRoom(examineRoomId);
					/* Hand the sheet to cashier*/
					ReleaseLock(cashierListLock);
					break;
				default:
					break;
			}
		}
		doTask();
	}
	totalNurseNum --;
	Exit(0);
}


void Doctor() {
	struct SheetEntry *myLocalSheet;
	int index;
	int arg1[1];
	int arg2[2];
	int arg3[3];
	int roomNum;
	int result;
	AcquireLock(currentDocLock);
	index = currentDoc++;
	ReleaseLock(currentDocLock);
	arg1[0] = index;
	arg2[0] = index;
	arg3[0] = index;
	
	while (1) {
		/* Stay in the office waiting for nurse's signal
		 After receiving the signal from nurse, doctor start to interact with the patient
		 Get the patient's examination sheet*/
		AcquireLock(doctorLock[index]);
		startSign --;
		AcquireLock(nurseDoctorLock);
		doctorState[index] = 1;
		ReleaseLock(nurseDoctorLock);
		WaitCondition(doctorCV[index], doctorLock[index]);
		if(test==7||test==6)
			myprintf("Doctor Office 2:Doctor [%d] is leaving their office.\n", arg1, 1);
		roomNum = doctorGoRoomId[index];
		AcquireLock(examineRoomPatientLock[roomNum]);
		/* Wake up the patient*/
		myLocalSheet = sheetForDoctor[index];
		doctorInRoom[roomNum] = index;
		SignalCondition(examineRoomPatientCV[roomNum], examineRoomPatientLock[roomNum]);
		ReleaseLock(examineRoomPatientLock[roomNum]);
		WaitCondition(doctorCV[index], doctorLock[index]);
		arg2[1] = roomNum;
		arg3[1] = myLocalSheet->id;
		arg3[2] = roomNum;
		if (myLocalSheet->state == 1){
			/* First time interact with the doctor
			 Start examination*/
			if (myLocalSheet->id < childNum){
				if(test==7||test==6)
					myprintf("Doctor Office 2:Doctor [%d] is reading the examination sheet of Child Patient [%d] in Examination room [%d].\n", arg3, 3);
			}
			else{
				if(test==7||test==6)
					myprintf("Doctor Office 2:Doctor [%d] is reading the examination sheet of Adult Patient [%d] in Examination room [%d].\n",  arg3, 3);                     
			}
			result = ++rand%4;
			switch (result) {
				case 0:
					/* Take Xray*/
					myLocalSheet->state = 3;
					patientneedto[myLocalSheet->id] = 3;
					/* Determin the number*/
					myLocalSheet->imageNum = 1+(++rand)%3;
					if (myLocalSheet->id < childNum){
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Xray is needed for Child Patient [%d] in Examination room [%d].\n",  arg3, 3);
					}
					else{
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Xray is needed for Adult Patient [%d] in Examination room [%d].\n",  arg3, 3);                                 
					}
					
					
					/*doctor ask patient to take xray and wait for the patient to come back*/
					break;
				case 1:
					/* Take shot*/
					myLocalSheet->state = 4;
					patientneedto[myLocalSheet->id] = 4;
					if (myLocalSheet->id < childNum){
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Child Patient [%d] needs to be given a shot in Examination room [%d].\n", arg3, 3);                                     
					}
					else{
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Adult Patient [%d] needs to be given a shot in Examination room [%d].\n", arg3, 3);                                                                           
					}
					
					break;
					
				default:
					/* Fine*/
					if (myLocalSheet->id < childNum){
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] diagnoses Child Patient [%d] to be fine and is leaving the Examination room [%d].\n", arg3, 3);
					}
					else{
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] diagnoses Adult Patient [%d] to be fine and is leaving the Examination room [%d].\n", arg3, 3);                                    
					}
					myLocalSheet->state = 2;                                      
			}
		}   
		else if (myLocalSheet->state == 5){ 
			result = ++rand%4;      
			if(test==7||test==6)           
				myprintf("Doctor Office 2:Doctor [%d] is examining the Xrays of [Adult/Child] Patient [%d] in Examination room [%d].\n", arg3, 3);
			switch (result) {
				case 0:
					/*need shot after xray*/
					myLocalSheet->state = 4;
					patientneedto[myLocalSheet->id] = 4;
					if (myLocalSheet->id < childNum){
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Child Patient [%d] needs to be given a shot in Examination room [%d].\n", arg3, 3);                                     
					}
					else{
						if(test==7||test==6)
							myprintf("Doctor Office 2:Doctor [%d] notes down in the sheet that Adult Patient [%d] needs to be given a shot in Examination room [%d].\n", arg3, 3);                                                                           
					}
					break;
				default:        
					myLocalSheet->state = 6;     
			}                               
		}
		SignalCondition(doctorCV[index], doctorLock[index]);
		WaitCondition(doctorCV[index], doctorLock[index]);
		AcquireLock(wallPocketLock);
		wallPocket[roomNum] = myLocalSheet;
		ReleaseLock(wallPocketLock);
		if(test==7||test==6)
			myprintf("Doctor Office 2:Doctor [%d] has left Examination Room [%d].\n", arg2, 2);
		ReleaseLock(doctorLock[index]);
		if(test==7||test==6)
			myprintf("Doctor Office 2:Doctor [%d] is going to their office.\n", arg1, 1);
	}
	Exit(0);
}


void Cashier(){
	int patientId;
	int arg1[2];
	int arg3[2];
	int arg2[3];
	int patientMoney;
	struct SheetEntry *myLocalSheet;
	/* Make sure the thread is executed before patient threads*/
	
	/* Work like the waiting room nurse*/
	while (1) {
		/* Check the line*/
		AcquireLock(cashierLineLock);
		startSign --;
		if (cashierLineNum == 0) {
			/* If no patient wait in the line, sleep until patient comes*/
			cashierState = 1;
		}else {
			/*If there are patients in the line signal one patient*/
			SignalCondition(cashierLineCV, cashierLineLock);
			cashierLineNum --;      /* Decrease the number of patients in the line*/
			cashierState = 2;
		}
		AcquireLock(cashierLock);
		ReleaseLock(cashierLineLock);
		WaitCondition(cashierCV, cashierLock);
		AcquireLock(cashierListLock);
		myLocalSheet = (SheetEntry *) DeQueue(&cashierList);
		ReleaseLock(cashierListLock);
		patientMoney = 10;
		if(myLocalSheet->shotOrNot == 1)
			patientMoney += 12;
		if(myLocalSheet->imageNum == 1 || myLocalSheet->imageNum == 2 || myLocalSheet->imageNum == 3)
			patientMoney += (15*myLocalSheet->imageNum);
		patientId = myLocalSheet->id;
		finalMoney[patientId] = patientMoney;
		arg1[0] = patientId;
		arg1[1] = patientMoney;
		arg2[0] = patientId;
		arg3[0] = patientMoney;
		arg3[1] = patientId;
		arg2[1] = patientId;
		arg2[2] = patientMoney;
		if (patientId < childNum){
			if(test==7||test==3||test==1)
				myprintf("Doctor Office 2:Cashier receives the examination sheet for Child Patient [%d] from Parent [%d].\n", arg2, 2);
		}
		else{
			if(test==7||test==3)
				myprintf("Doctor Office 2:Cashier receives the examination sheet from Adult Patient[%d].\n", arg1, 1);          
		}
		/*Wait patient to pay*/
		SignalCondition(cashierCV, cashierLock);
		if (patientId < childNum){
			if(test==7||test==1||test==3)
				myprintf("Doctor Office 2:Cashier reads the examination sheet of Child Patient [%d] and asks Parent [%d] to pay $ %d \n", arg2, 3);
		}
		else{
			if(test==7||test==3)
				myprintf("Doctor Office 2:Cashier reads the examination sheet of Adult Patient [%d] and asks him to pay $ %d\n", arg1, 2);
		}
		WaitCondition(cashierCV, cashierLock);
		if (patientId < childNum){
			if(test==7||test==3||test==1)
				myprintf("Doctor Office 2:Cashier accepts $ %d from Parent [%d].\n", arg3, 2);
		}
		else{
			if(test==7||test==3)
				myprintf("Doctor Office 2:Cashier accepts $ %d from Adult Patient [%d].\n", arg3, 2);                  
		}
		/* Wait for patient leaving*/
		SignalCondition(cashierCV, cashierLock);
		if (patientId < childNum){
			if(test==7||test==3||test==1)
				myprintf("Doctor Office 2:Cashier gives a receipt of $ %d to Parent [%d].\n", arg3, 2);
		}
		else{
			if(test==7||test==3)
				myprintf("Doctor Office 2:Cashier gives a receipt of $ %d to Adult Patient [%d].\n", arg3, 2);
		}
		WaitCondition(cashierCV, cashierLock);
		/* loop*/
		if (totalPatientNum <= 0) {
			break;
		}
		ReleaseLock(cashierLock);
	}
}

void XRayTechnician(){
	int index;
	int i;
	int imageNum;
	int arg[2];
	int result;
	struct SheetEntry *myLocalSheet;
	AcquireLock(currentxRayLock);
	index = currentxRay++;
	ReleaseLock(currentxRayLock);
	arg[0] = index;
	while (1) {
	 	/* Wait until a Nurse brings a Patient
		 Get the patient's exemination sheet*/
		AcquireLock(xRayWaitLineLock[index]);
		startSign --;
		if (xRayWaitLineNum[index] == 0){
			/* If no patient wait in the line, sleep until patient comes*/
			xtechnicianstate[index] = 1;
		}
		else{
			/*If there are patients in the line signal one patient*/
			SignalCondition(xRayWaitLineCV[index], xRayWaitLineLock[index]);
			xRayWaitLineNum[index] --;      /* Decrease the number of patients in the line*/
			xtechnicianstate[index] = 2;
		}
		AcquireLock(xRayLock[index]);
		ReleaseLock(xRayWaitLineLock[index]);
		WaitCondition(xRayCV[index], xRayLock[index]);
		AcquireLock(waitListLock[index]);
		myLocalSheet = (SheetEntry *) DeQueue(&xrayWaitList[index]);
		ReleaseLock(waitListLock[index]);
		imageNum = myLocalSheet->imageNum;
		xtImageNum[index] = imageNum;
		/* Wait for the patient getting onto the table
		 Take images
		 Stay in xray room waiting for nurse's signal
		 After receiving the signal from nurse, xray technician start to interact with the patient
		 Get the patient's examination sheet
		 
		 Patient comes
		 technician take 3 images */
		arg[0] = index;
		arg[1] = myLocalSheet->id;
		if (myLocalSheet->id < childNum){
			if(test==7)
				myprintf("Doctor Office 2:Xray technician [%d] asks Child Patient [%d] to get on the table.\n", arg, 2);
		}
		else{
			if(test==7)
				myprintf("Doctor Office 2:Xray technician [%d] asks Adult Patient [%d] to get on the table.\n", arg, 2);	
		}
		SignalCondition(xRayCV[index], xRayLock[index]);
		WaitCondition(xRayCV[index], xRayLock[index]);
		for (i=0;i < imageNum;i++){
			if (myLocalSheet->id < childNum){
				if(test==7)
					myprintf("Doctor Office 2:Xray Technician [%d] takes an Xray Image of Child Patient [%d].\n", arg, 2);
			}
			else{
				if(test==7)
					myprintf("Doctor Office 2:Xray Technician [%d] takes an Xray Image of Adult Patient [%d].\n", arg, 2);				
			}
			result = ++rand%3;
			switch (result) {
				case 0:
					myLocalSheet->xrayResults[i] = 1;
					if (myLocalSheet->id < childNum){
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records nothing on Child Patient [%d] 's examination sheet.\n", arg, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records nothing on Adult Patient [%d] 's examination sheet.\n", arg, 2);						
					}
					break;
				case 1:
					myLocalSheet->xrayResults[i] = 2;
					if (myLocalSheet->id < childNum){
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records break on Child Patient [%d] 's examination sheet.\n", arg, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records break on Adult Patient [%d] 's examination sheet.\n", arg, 2);						
					}					
					break;
				case 2:
					myLocalSheet->xrayResults[i] = 3;
					if (myLocalSheet->id < childNum){
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records compound fracture on Child Patient [%d] 's examination sheet.\n", arg, 2);
					}
					else{
						if(test==7)
							myprintf("Doctor Office 2:Xray Technician [%d] records compound fracture on Adult Patient [%d] 's examination sheet.\n", arg, 2);						
					}							
					break;
			}
			/*printf("xRay technician [%d] wrote image [%d] on patient [%d] sheet\n", index, i, myLocalSheet->id);*/  
			if (i+1 < imageNum) {
				if (myLocalSheet->id < childNum){
					if(test==7)
						myprintf("Doctor Office 2:Xray Technician [%d] asks Child Patient [%d] to move.\n", arg, 2);
				}
				else{
					if(test==7)
						myprintf("Doctor Office 2:Xray Technician [%d] asks Adult Patient [%d] to move.\n", arg, 2);					
				}
				SignalCondition(xRayCV[index], xRayLock[index]);
				WaitCondition(xRayCV[index], xRayLock[index]);
			}
		}
		myLocalSheet->state = 5;
		AcquireLock(finishListLock);
		InQueue(&xrayFinishList, myLocalSheet);
		if (myLocalSheet->id < childNum){
			if(test==7||test==1){
				myprintf("Doctor Office 2:X-ray Technician [%d] tells Parent [%d] to wait in Xray waiting room.\n", arg, 2);
				myprintf("Doctor Office 2:X-ray Technician [%d] puts Parent [%d] in Xray waiting room wall pocket.\n", arg, 2);
			}
		}else{
			if(test==7){
				myprintf("Doctor Office 2:X-ray Technician [%d] tells Adult Patient [%d] to wait in Xray waiting room.\n", arg, 2);
				myprintf("Doctor Office 2:X-ray Technician [%d] puts Adult Patient [%d] in Xray waiting room wall pocket.\n", arg, 2);
			}
			
		}
		SignalCondition(xRayCV[index], xRayLock[index]);
		WaitCondition(xRayCV[index], xRayLock[index]);
		ReleaseLock(xRayLock[index]);
		ReleaseLock(finishListLock);
	}
	Exit(0);
}

void CleanUp(int patientNum){
	int i;
	DestroyLock(currentxRayLock);
	DestroyLock(currentDocLock);
	DestroyLock(currentNurseLock);
	DestroyLock(currentPatientLock);
	DestroyLock(currentChildLock);
	
	DestroyLock(wrnLock);
	DestroyLock(wrnLineLock);
	DestroyCondition(wrnCV);
	DestroyCondition(wrnLineCV);
	
	DestroyLock(cashierLineLock);
	DestroyLock(cashierLock);
	DestroyLock(cashierListLock);
	DestroyCondition(cashierLineCV);
	DestroyCondition(cashierCV);
	
	DestroyLock(cabinetLock);
	DestroyLock(nurseDoctorLock);
	DestroyCondition(nurseWrnLineCV);
	
	/* Examine room*/
	for (i=0; i<MAX_NUM_ROOMS; i++) {
		DestroyLock(examineRoomPatientLock[i]);
		DestroyCondition(examineRoomPatientCV[i]);
	}
	
	/* Xray Technician*/
	DestroyLock(finishListLock);
	for (i=0; i<MAX_NUM_XTECH; i++) {
		DestroyLock(xRayWaitLineLock[i]);
		DestroyCondition(xRayWaitLineCV[i]);
		DestroyLock(xRayLock[i]);
		DestroyCondition(xRayCV[i]);
		DestroyLock(waitListLock[i]);
	}
	
	/* Patient*/
	for (i=0; i<patientNum+childNum; i++) {
		if (i >= childNum) {
			DestroyLock(patientLock[i]);
			DestroyCondition(patientCV[i]);
		}
		else{
			DestroyLock(childLock[i]);
			DestroyCondition(childCV[i]);
			DestroyLock(patientLock[i]);
			DestroyCondition(patientCV[i]);
		}
	}
	
	/* Doctor*/
	for (i=0; i<MAX_NUM_DOCTORS; i++) {
		DestroyLock(doctorLock[i]);
		DestroyCondition(doctorCV[i]);
	}
	
}

void Initialize(int patientNum, int xtechNum, int doctorNum, int examRoomNum) {
	int arg[1];
	int i;
	int j;
	startSign = 0;
	
	arg[0] = doctorNum;
	myprintf("Doctor Office 2:Number of Doctors = [%d]\n", arg, 1);
	arg[0] = totalNurseNum;
	myprintf("Doctor Office 2:Number of Nurses = [%d]\n", arg, 1);
	arg[0] = xtechNum;
	myprintf("Doctor Office 2:Number of XRay Technicians = [%d]\n", arg, 1);
	arg[0] = patientNum;
	myprintf("Doctor Office 2:Number of Adult Patients = [%d]\n", arg, 1);
	arg[0] = childNum;
	myprintf("Doctor Office 2:Number of Parents/Child Patients = [%d]\n", arg, 1);
	arg[0] = examRoomNum;
	myprintf("Doctor Office 2:Number of Examination Rooms = [%d]\n", arg, 1);
	
	currentxRayLock = CreateLock("lock1", 5);
	currentDocLock = CreateLock("lock2", 5);
	currentNurseLock = CreateLock("lock3", 5);
	currentPatientLock = CreateLock("lock4", 5);
	currentChildLock = CreateLock("lock5", 5);
	
	/* Waiting room nurse*/
	wrnState = 1;
	wrnLock = CreateLock("wrnLock", 7);
	wrnCV = CreateCondition("wrnCV", 5);
	wrnLineLock = CreateLock("wrnLineLock", 11);
	wrnLineCV = CreateCondition("wrnLineCV", 9);
	wrnLineNum = 0;
	wrnList.head = wrnList.tail = 0;
	wrnList.number = 0;
	
	/* Cashier*/
	cashierState = 1;
	cashierLineLock = CreateLock("cashierLineLock", 15);
	cashierLineCV = CreateCondition("cashierLineCV", 13);
	cashierLock = CreateLock("cashierLock", 11);
	cashierCV = CreateCondition("cashierCV", 9);
	cashierLineNum = 0;
	cashierListLock = CreateLock("cashierListLock", 15);
	cashierList.head = cashierList.tail = 0;
	cashierList.number = 0;
	
	/* Nurse*/
	cabinetLock = CreateLock("cabinetLock", 11);
	nurseDoctorLock = CreateLock("nurseDoctorLock", 15);
	nurseWrnLineCV = CreateCondition("nurseWrnLineCV", 14);
	nurseWrnCount = 0;
	patientWaitNum = 0;
	
	/* Examine room*/
	wallPocketLock = CreateLock("wallPocketLock", 14);
	for (i=0; i<MAX_NUM_ROOMS; i++) {
		if (i < examRoomNum) {
			examineRoom[i] = 1;
			examineRoomPatientLock[i] = CreateLock("examineRoomPatientLock", 22);
			examineRoomPatientCV[i] = CreateCondition("examineRoomPatientCV", 20);
		}else {
			examineRoom[i] = 3;
			examineRoomPatientLock[i] = -1;
			examineRoomPatientCV[i] = -1;
		}
		wallPocket[i] = 0;
	}
	
	/* Xray Technician*/
	xRayTechNum = xtechNum;
	finishListLock = CreateLock("finishListLock", 14);
	xrayFinishList.head = xrayFinishList.tail = 0;
	xrayFinishList.number = 0;
	for (i=0; i<MAX_NUM_XTECH; i++) {
		if (i < xtechNum) {
			xtechnicianstate[i] = 1;
			xRayWaitLineLock[i] = CreateLock("xRayWaitLineLock", 16);
			xRayWaitLineCV[i] = CreateCondition("xRayWaitLineCV", 14);
			xRayLock[i] = CreateLock("xRayLock", 8);
			xRayCV[i] = CreateCondition("xRayCV", 6);
			waitListLock[i] = CreateLock("waitListLock", 12);
			xrayWaitList[i].head = xrayWaitList[i].tail = 0;
			xrayWaitList[i].number = 0;
		}
		else{
            xtechnicianstate[i] = 3;
			xRayWaitLineLock[i] = -1;
			xRayWaitLineCV[i] = -1;
			xRayLock[i] = -1;
			xRayCV[i] = -1;
			waitListLock[i] = -1;
		}
		xRayWaitLineNum[i] = 0;
	}
	
	/* Patient*/
	totalPatientNum = patientNum+childNum;
	for (i=0; i<patientNum+childNum; i++) {
		if (i < childNum) {
			childLock[i] = CreateLock("childLock", 9);
			childCV[i] = CreateCondition("childCV", 7);
		}
		
		patientLock[i] = CreateLock("patientLock", 11);
		patientCV[i] = CreateCondition("patientCV", 9);
		roomId[i] = -1;
		xtIdWithPatient[i] = -1;
		patientneedto[i] = 1;
		symptomResponse[i] = 2;
		patientWithNurse[i] = -1;
		isChild[i] = 0;
		finalMoney[i] = 0;
	}
	
	/* Doctor*/
	for (i=0; i<MAX_NUM_DOCTORS; i++) {
		if (i < doctorNum) {
			doctorState[i] = 1;
			doctorLock[i] = CreateLock("doctorLock", 10);
			doctorCV[i] = CreateCondition("doctorCV", 8);
		}
		else{
			doctorState[i] = 3;
			doctorLock[i] = -1;
			doctorCV[i] = -1;
		}
	}
}



int main() {
	int flag;
	int i;
	int quit = 0;
	int input;
	int patientNum = 0;
	int examRoomNum = 0;
	int xtechNum = 0;
	int doctorNum = 0;
	int arg[1];
	childNum = 0;	
	totalNurseNum = 0;
	currentxRay = 0;
	currentDoc = 0;
	currentNurse = 0;
	currentPatient = 0;
	currentChild = 0;
	rand = 0;
	test = 7;
	totalNurseNum = 5;
	childNum = 30;
	patientNum = 30;
	examRoomNum = 5;
	xtechNum = 2;
	doctorNum = 3;
		
	Initialize(patientNum, xtechNum, doctorNum, examRoomNum);
		
	startSign = 2+doctorNum+xtechNum;
	/* Fork the threads*/
	Fork(WaitingRoomNurse);
	for (i=0; i<xtechNum; i++) {
		Fork(XRayTechnician);
	}
		
	for (i=0; i<totalNurseNum; i++) {
		Fork(Nurse);
	}
		
	for (i=0; i<doctorNum; i++) {
		Fork(Doctor);
	}
		
	for (i=0; i<patientNum+childNum; i++) {
		if (i<childNum) {
			Fork(AdultPatient);
			Fork(ChildPatient);
		}else {
			Fork(AdultPatient);
		}
	}
	Cashier();
	while (totalNurseNum > 0 || totalPatientNum > 0) {
		Yield();
	}
	CleanUp(patientNum);
	
	return 0;
}
